package com.dkd.manage.task.allocator.algorithm;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FuzzyLogicEvaluator {

    public double evaluate(double workload, double skillMatch, double distance, double performance) {
        log.debug("模糊逻辑评估 - 负载: {}, 技能匹配: {}, 距离: {}, 性能: {}", workload, skillMatch, distance, performance);

        // 模糊化输入
        double workloadLow = fuzzyLow(workload);
        double workloadMedium = fuzzyMedium(workload);
        double workloadHigh = fuzzyHigh(workload);

        double skillMatchLow = fuzzyLow(skillMatch);
        double skillMatchMedium = fuzzyMedium(skillMatch);
        double skillMatchHigh = fuzzyHigh(skillMatch);

        double distanceClose = fuzzyLow(distance);
        double distanceMedium = fuzzyMedium(distance);
        double distanceFar = fuzzyHigh(distance);

        double performanceLow = fuzzyLow(performance);
        double performanceMedium = fuzzyMedium(performance);
        double performanceHigh = fuzzyHigh(performance);

        // 模糊规则库
        double score = 0.0;
        double totalWeight = 0.0;

        // 规则1: 如果负载低且技能匹配高，则评分高
        double rule1 = Math.min(workloadLow, skillMatchHigh);
        score += rule1 * 9.0;
        totalWeight += rule1;

        // 规则2: 如果负载中等、技能匹配中等且距离近，则评分中等偏高
        double rule2 = Math.min(Math.min(workloadMedium, skillMatchMedium), distanceClose);
        score += rule2 * 7.5;
        totalWeight += rule2;

        // 规则3: 如果性能高且技能匹配中等，则评分中等
        double rule3 = Math.min(performanceHigh, skillMatchMedium);
        score += rule3 * 6.5;
        totalWeight += rule3;

        // 规则4: 如果负载高或距离远，则评分低
        double rule4 = Math.max(workloadHigh, distanceFar);
        score += rule4 * 3.0;
        totalWeight += rule4;

        // 规则5: 默认规则
        if (totalWeight < 0.1) {
            score += 5.0;
            totalWeight += 1.0;
        }

        // 解模糊（加权平均）
        double finalScore = totalWeight > 0 ? score / totalWeight : 5.0;

        log.debug("模糊逻辑评估完成，最终评分: {}", finalScore);
        return finalScore;
    }

    private double fuzzyLow(double x) {
        return Math.max(0, 1 - x * 2);
    }

    private double fuzzyMedium(double x) {
        return Math.max(0, 1 - Math.abs(x - 0.5) * 2);
    }

    private double fuzzyHigh(double x) {
        return Math.max(0, (x - 0.5) * 2);
    }
}